﻿using System;
using System.Text;
using System.Drawing;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;

public static partial class NativeAOT
{
    [UnmanagedCallersOnly(EntryPoint = "snse")]
    public static unsafe int snse(int n, double eps, IntPtr x_ptr, IntPtr f_xa_ya_n_ptr, int inter)
    {
        double* x = (double*)x_ptr.ToPointer();
        f_xa_ya_n = Marshal.GetDelegateForFunctionPointer<delegatefunc_xa_ya_n>(f_xa_ya_n_ptr);

        return snse(n, eps, x, inter);
    }

    /// <summary>
    /// 非线性方程组梯度法
    /// f(double[] x, double[] y, int n)计算目标函数值以及目标函数n个偏导数的函数名。
    /// </summary>
    /// <param name="n">n方程个数，也是未知数个数。</param>
    /// <param name="eps">eps控制精度要求。</param>
    /// <param name="x">x[n]存放一组初值。返回一组实数解。</param>
    /// <returns>函数返回实际迭代次数。若<0则表示因D=0而失败。本函数最大迭代次数为1000。</returns>
    public static unsafe int snse(int n, double eps, double* x, int inter = 1000)
    {
        int i, k, flag;
        double y, d, s;
        double* yy = stackalloc double[n];

        k = 0;
        flag = 0;
        while ((k < inter) && (flag == 0))
        {
            //计算目标函数值F以及目标函数的n个偏导数
            y = f_xa_ya_n(x, yy, n);
            if (y < eps)
            {
                flag = 1;
            }
            else
            {
                k = k + 1;
                d = 0.0;
                //计算D
                for (i = 0; i <= n - 1; i++)
                {
                    d = d + yy[i] * yy[i];
                }
                if (d + 1.0 == 1.0)
                {
                    return (-1);
                }
                s = y / d;
                for (i = 0; i <= n - 1; i++)
                {
                    //计算新的校正值X
                    x[i] = x[i] - s * yy[i];
                }
            }
        }
        return (k);
    }

    /*
    // 非线性方程组梯度法例
      int main()
      { 
          int i,k;
          double eps, snsef(double [], double [], int);
          double x[3]={1.5,6.5,-5.0};
          eps=0.000001;
          k = snse(3,eps,x,snsef);
          cout <<"迭代次数 = " <<k <<endl;
          for (i=0; i<=2; i++)
                 cout <<"x(" <<i <<")=" <<x[i] <<endl;
          return 0;
      }

      double snsef(double x[],double y[],int n)
      { double z,f1,f2,f3,df1,df2,df3;
        n=n;        f1=x[0]-5.0*x[1]*x[1]+7.0*x[2]*x[2]+12.0;
        f2=3.0*x[0]*x[1]+x[0]*x[2]-11.0*x[0];
        f3=2.0*x[1]*x[2]+40.0*x[0];
        z=f1*f1+f2*f2+f3*f3;
        df1=1.0; df2=3.0*x[1]+x[2]-11.0; df3=40.0;
        y[0]=2.0*(f1*df1+f2*df2+f3*df3);
        df1=-10.0*x[1]; df2=3.0*x[0]; df3=2.0*x[2];
        y[1]=2.0*(f1*df1+f2*df2+f3*df3);
        df1=14.0*x[2]; df2=x[0]; df3=2.0*x[1];
        y[2]=2.0*(f1*df1+f2*df2+f3*df3);
        return(z);
      }
    */
}

